import functools
import inspect

_matchers = {}

def matcher(matcher_name):
    def decorator(func):
        _matchers[matcher_name] = func
        return func
    return decorator


def raw_func_generator(func, **fixed_kwargs):
    sig = inspect.signature(func)

    @functools.wraps(func)
    def generated(*args, **kwargs):
        all_kwargs = dict(kwargs)
        for name, value in fixed_kwargs.items():
            if name in sig.parameters:
                all_kwargs[name] = value
        return func(*args, **all_kwargs)

    name_suffix = "_".join(f"{k}_{v}" for k, v in fixed_kwargs.items())
    generated.__name__ = f"{func.__name__}_{name_suffix}"

    generated._template = func
    generated._fixed_kwargs = fixed_kwargs
    return generated

def func_generator(matcher_name,**fixed_kwargs):
    return raw_func_generator(_matchers[matcher_name],**fixed_kwargs)